<?php
/**
 * Copyright (C) 2013 Pablo Sepúlveda P. <psep.pentauc@gmail.com>
 * 
 * This file is part of gAbstract.
 * WarpIT is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * gAbstract is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with gAbstract.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Clase de utilidad para la manupulación
 * de Objetos.
 * 
 * @author psep
 * @version 1.0
 * @package gAbstract
 * @copyright Copyright (c) 2013 Pablo Sepúlveda P.
 * @license GNU GPLv3 or later
 * @link http://www.psep.cl
 */
final class ObjectUtil{
	
	/**
	 * Método estático que transforma array
	 * en un objeto de tipo stdClass.
	 * 
	 * @param $array
	 * @return stdClass object
	 */
	public static function arrayToObject($array){
		return (Object) $array; 
	}
	
	/**
	 * Método estático que permite la conversión
	 * de un Object genérico en un objeto de
	 * naturaleza definida por el valor $destination.
	 * 
	 * @param $destination Instancia de objeto de destino.
	 * @param $source stdClass object
	 * @return cast object
	 */
	public static function cast($destination, \stdClass $source){
		$sourceReflection = new \ReflectionObject($source);
		$sourceProperties = $sourceReflection->getProperties();

		foreach ($sourceProperties as $sourceProperty) {
			$name = $sourceProperty->getName();
			call_user_func(array($destination, "set".NameUtils::formalName($name)), $source->$name);
		}
		
		return $destination;
	}
	
	/**
	 * Método que retorna el id de un objeto.
	 * 
	 * @param Object
	 * @return String
	 */
	public static function getIdName($object){
		$reflection = new \ReflectionObject($object);
		$properties = $reflection->getProperties();
		$obj 		= $properties[0];
		return $obj->getName();
	}
	
	/**
	 * Método que retorna ID de un objeto con atributos
	 * para la generación de querys:
	 * 
	 * $data[0] = 'nombre de columna = ?' |
	 * $data[1] = 'valor del atributo id del objeto'
	 * 
	 * @param Object
	 * @return array
	 */
	public static function getIdObjectValue($object){
		$reflection = new \ReflectionObject($object);
		$properties = $reflection->getProperties();
		$obj 		= $properties[0];
		$name		= $obj->getName();
		$foo		= $reflection->getProperty($name);
		$foo->setAccessible(true);

		return array($name." = ?", $foo->getValue($object));
	}
	
	/**
	 * Método que retorna ID de un objeto con atributos
	 * para la generación de querys:
	 * 
	 * $data[0] = 'nombre de columna = ?' |
	 * $data[1] = 'valor del atributo id del objeto' |
	 * $data[2] = 'parámetro para atributo PDO::PARAM_*'
	 * 
	 * Si la validación falla, retorna nulo.
	 * 
	 * @param Object
	 * @return array
	 */
	public static function validateId($object){
		$data = static::getIdObjectValue($object);
		
		if($data == null || count($data) == 0){
			return null;
		}else if(is_integer($data[1])){
			$data[] = 3;
		}else if(is_string($data[1])){
			$data[] = 4;
		}
		
		return $data;
	}
	
	/**
	 * Método que retorna los datos no nulos ni vacíos
	 * de un objetos formateados como array para posterior
	 * statement.
	 * Format: array[n]{nombre = ?, valor}
	 * 
	 * @param object
	 * @return array
	 */
	public static function searchValueObject($object){
		$reflection = new \ReflectionObject($object);
		$properties = $reflection->getProperties();
		$data		= array();
		$puntero	= 0;
		
		foreach ($properties as $field) {
			$name	= $field->getName();
			$foo	= $reflection->getProperty($name);
			$foo->setAccessible(true);
			$fValue	= $foo->getValue($object);
			
			if($fValue != null && trim($fValue) != ""){
				$data[$puntero] = array($name.' = ?', $fValue);
				
				if(is_integer($fValue)){
					$data[$puntero][] = 3;
				}else if(is_string($fValue)){
					$data[$puntero][] = 4;
				}else if(is_bool($fValue)){
					$data[$puntero][] = 1;
				}
				
				$puntero++;
			}
		}
		
		return $data;
		
	}
	
	/**
	 * Método que retorna el valor de todos los atributos
	 * como array del objeto ingresado como parámetro.
	 * 
	 * @param Object
	 * @return array
	 */
	public static function attrValuesObject($object){
		$reflection = new \ReflectionObject($object);
		$properties = $reflection->getProperties();
		$data		= array();
		
		foreach ($properties as $field) {
			$name	= $field->getName();
			$foo	= $reflection->getProperty($name);
			$foo->setAccessible(true);
			$data[]	= $foo->getValue($object);
		}
		
		return $data;

	}
	
	/**
	 * Método que recibe como parámetro un objeto y
	 * retorna el nombre de sus atributos en un array.
	 * 
	 * @param Object
	 * @return array
	 */
	public static function getAttributesOfObject($object){
		$sourceReflection	= new \ReflectionObject($object);
		$sourceProperties	= $sourceReflection->getProperties();
		$fields				= array();
		
		foreach ($sourceProperties as $sourceProperty) {
			$fields[] = $sourceProperty->getName();
		}
		
		return $fields;
	}
	
	/**
	 * Método que valida si el parámetro ingresado es un objeto
	 * o una lista de objetos. Si es un objeto, lo ingresa a una
	 * lista que será retornada, sino, retornará la lista intacta.
	 * 
	 * @param mixed Object-List
	 * @return array (lista de objetos)
	 */
	public static function objectToList($object){
		$list = array();
			
		if(!is_array($object)){
			$list[]	= $object;
		}else{
			$list = $object;
		}
		
		return $list;
	}
	
	/**
	 * Método que adapta tipos de datos de
	 * DB para utilización de código.
	 * Si se ingresa como parámetro adicional
	 * el entero 1, retorna el nombre original
	 * del campo por default.
	 * 
	 * @param String
	 * @param Integer
	 * @return String
	 */
	public static function getTypeDB($val, $int = 0){
		switch ($val) {
			case "varchar":		return "string"; break;
			case "bigint":		return "integer";break;
			case "longtext":	return "string"; break;
			case "char":		return "string"; break;
			case "mediumtext":	return "string"; break;
			case "text":		return "string"; break;
			case "int":			return "integer";break;
			case "smallint":	return "integer";break;
			case "decimal":		return "float";  break;
			case "double":		return "float";  break;
			case "tinyint":		return "boolean";break;
			default: 
				if($int == 1){
					return $val;
				}else{
					return null;
				}; break;
		}
	}
	
}

?>